﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using NAccounting.Models;
using AutoMapper;
using System.Threading;

namespace NAccounting
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            BundleTable.Bundles.RegisterTemplateBundles();

            RegisterBundles();
            ConfigureMappers();
        }

        private void ConfigureMappers()
        {
            var culture = Thread.CurrentThread.CurrentUICulture;

            Mapper.CreateMap<Lot, LotDetailModel>()
                  .ForMember(x => x.OpenDate, opt => opt.MapFrom(s => s.OpenDate.ToStringForNullable((culture.DateTimeFormat.ShortDatePattern))))
                  .ForMember(x => x.PeriodStart, opt => opt.MapFrom(s => s.StartPeriod.ToString(culture.DateTimeFormat.ShortDatePattern)))
                  .ForMember(x => x.PeriodEnd, opt => opt.MapFrom(s => s.EndPeriod.ToString(culture.DateTimeFormat.ShortDatePattern)))
                  .ForMember(x => x.PeriodStartJs, opt => opt.MapFrom(s => s.StartPeriod.ToJsString()))
                  .ForMember(x => x.PeriodEndJs, opt => opt.MapFrom(s => s.EndPeriod.ToJsString()))
                  .ForMember(x => x.HasOpenDate, opt => opt.MapFrom(s => s.OpenDate.HasValue))
                  .ForMember(x => x.HasCloseDate, opt => opt.MapFrom(s => s.CloseDate.HasValue))
                  .ForMember(x => x.CloseDate, opt => opt.MapFrom(s => s.CloseDate.ToStringForNullable()))
                  .ForMember(x => x.TotalCredit, opt => opt.MapFrom(s => s.TotalCredit.ToCurrencyString()))
                  .ForMember(x => x.TotalDebit, opt => opt.MapFrom(s => s.TotalDebit.ToCurrencyString()))
                  .ForMember(x => x.HasReleases, opt => opt.MapFrom(s => s.AccountEntries.Count > 0))
                  .ForMember(x => x.CanCloseLote, opt => opt.MapFrom(s => !s.CloseDate.HasValue))
                  .ForMember(x => x.CanSave, opt => opt.MapFrom(s => s.AccountEntries.Count == 0));

            Mapper.CreateMap<LotDetailModel, Lot>()
                  .ForMember(x => x.OpenDate, opt => opt.ResolveUsing(s => String.IsNullOrWhiteSpace(s.OpenDate) ? default(DateTime?) : Convert.ToDateTime(s.PeriodStart)))
                  .ForMember(x => x.StartPeriod, opt => opt.ResolveUsing(s => Convert.ToDateTime(s.PeriodStart)))
                  .ForMember(x => x.EndPeriod, opt => opt.ResolveUsing(s => Convert.ToDateTime(s.PeriodEnd)));

            Mapper.CreateMap<AccountEntry, AccountEntryDetailModel>()
                  .ForMember(x => x.LotDescription, opt => opt.MapFrom(s => s.Lot.Description))
                  .ForMember(x => x.LotPeriod, opt => opt.MapFrom(s => String.Format("{0} até {1}", s.Lot.StartPeriod.ToString(culture.DateTimeFormat.ShortDatePattern), s.Lot.EndPeriod.ToString(culture.DateTimeFormat.ShortDatePattern))))
                  .ForMember(x => x.MinDateJs, opt => opt.MapFrom(s => s.Lot.StartPeriod.ToJsString()))
                  .ForMember(x => x.MaxDateJs, opt => opt.MapFrom(s => s.Lot.EndPeriod.ToJsString()))
                  .ForMember(x => x.LotIsValidJs, opt => opt.MapFrom(s => s.Lot.MayReceiveRelease.ToString().ToLower()))
                  .ForMember(x => x.AccountEntryDate, opt => opt.MapFrom(s => s.Date.ToString(culture.DateTimeFormat.ShortDatePattern)))
                  .ForMember(x => x.AccountPlanDescription, opt => opt.MapFrom(s => s.AccountPlan.ToString()))
                  .ForMember(x => x.CanDelete, opt => opt.MapFrom(s => s.CanDelete.ToString().ToLower()))
                  .ForMember(x => x.AccountEntryId, opt => opt.MapFrom(s => s.Id))
                  .ForMember(x => x.LotTotalCredit, opt => opt.MapFrom(s => s.Lot.TotalCredit.ToCurrencyString()))
                  .ForMember(x => x.LotTotalDebit, opt => opt.MapFrom(s => s.Lot.TotalDebit.ToCurrencyString()));

            Mapper.CreateMap<AccountEntryDetailModel, AccountEntry>()
                  .ForMember(x => x.Date, opt => opt.ResolveUsing(s => Convert.ToDateTime(s.AccountEntryDate)))
                  .ForMember(x => x.Value, opt => opt.ResolveUsing(s => Convert.ToDecimal(s.Value)))
                  .ForMember(x => x.Id, opt => opt.MapFrom(s => s.AccountEntryId));

            Mapper.CreateMap<AppointmentDetailModel, Appointment>()
                  .ForMember(x => x.Date, opt => opt.ResolveUsing(s => Convert.ToDateTime(s.Date)))
                  .ForMember(x => x.StartMoment, opt => opt.ResolveUsing(s => DateTime.ParseExact(s.StartTime, "HH:mm", culture)))
                  .ForMember(x => x.EndMoment, opt => opt.ResolveUsing(s => DateTime.ParseExact(s.EndTime, "HH:mm", culture)));

            Mapper.CreateMap<Appointment, AppointmentDetailModel>()
                  .ForMember(x => x.StartTime, opt => opt.ResolveUsing(s => s.StartMoment.ToShortTimeString()))
                  .ForMember(x => x.EndTime, opt => opt.ResolveUsing(s => s.EndMoment.HasValue ? s.EndMoment.Value.ToShortTimeString(): ""))
                  .ForMember(x => x.Project, opt => opt.ResolveUsing(s => s.ProjectActivity.Project.Name))
                  .ForMember(x => x.Date, opt => opt.ResolveUsing(s => s.Date.ToString("MM/dd/yyyy")));

            Mapper.CreateMap<Project, ProjectDetailsModel>();

            Mapper.CreateMap<ProjectActivity, ActivityDetailsModel>()
                  .ForMember(x => x.ProjectName, opt => opt.ResolveUsing(s => s.Project.Name));

            Mapper.CreateMap<ActivityDetailsModel, ProjectActivity>();
        }

        private static void RegisterBundles()
        {
            var jqgridBundle = new Bundle("~/Scripts/jqgrid");
            jqgridBundle.AddFile("~/Scripts/grid.locale-pt-br.js", throwIfNotExist: true);
            jqgridBundle.AddFile("~/Scripts/jquery.jqGrid.min.js", throwIfNotExist: true);
            BundleTable.Bundles.Add(jqgridBundle);

            var jqgridCssBundle = new Bundle("~/Content/jqgrid");
            jqgridCssBundle.AddFile("~/Content/ui.jqgrid.css", throwIfNotExist: true);
            BundleTable.Bundles.Add(jqgridCssBundle);

            var environmentBunble = new Bundle("~/Scripts/environment", new JsMinify());
            environmentBunble.AddFile("~/Scripts/environment.js", throwIfNotExist: true);
            environmentBunble.AddFile("~/Scripts/jquery.messageContainer.js", throwIfNotExist: true);
            BundleTable.Bundles.Add(environmentBunble);

            var masksBundle = new Bundle("~/Scripts/mask");
            masksBundle.AddFile("~/Scripts/jquery.placeholder.js", throwIfNotExist: true);
            masksBundle.AddFile("~/Scripts/jquery.maskMoney.js", throwIfNotExist: true);
            BundleTable.Bundles.Add(masksBundle);

            var jqueryUiBundle = new Bundle("~/Scripts/jqueryui");
            jqueryUiBundle.AddFile("~/Scripts/jquery.ui.datepicker-pt-BR.js", throwIfNotExist: true);
            jqueryUiBundle.AddFile("~/Scripts/jquery.ui.combobox.js", throwIfNotExist: true);
            jqueryUiBundle.AddFile("~/Scripts/jquery.timeentry.min.js", throwIfNotExist: true);
            BundleTable.Bundles.Add(jqueryUiBundle);
        }
    }
}